今回はテクスチャのアニメーションの実装方法についてみていく。テクスチャのアニメーションもメッシュ・アニメーションと同様、meshに対してテクスチャを定期的に設定しなおすことで実現できる。なお、JavaFXにおけるアニメーションの基礎は『
JavaFX アニメーション』を参照のこと。
■ テクスチャ・アニメーションのサンプル
以下にテクスチャ・アニメーションを行うサンプルコードを示す。サンプルでは、0.5行毎にテクスチャ画像を入れ替える。
◇ サンプルコード
package application_fx;
import java.io.File;
import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.LightBase;
import javafx.scene.Node;
import javafx.scene.PerspectiveCamera;
import javafx.scene.PointLight;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.paint.Color;
import javafx.scene.paint.PhongMaterial;
import javafx.scene.shape.CullFace;
import javafx.scene.shape.MeshView;
import javafx.scene.shape.TriangleMesh;
import javafx.stage.Stage;
public class TestTriangleMeshTexture extends Application {
public static void main(String[] args)
{
launch( args );
}
@Override
public void start(Stage primaryStage) throws Exception
{
// シーングラフの構成
Group root = new Group();
// モデルデータの取り込み
root.getChildren().add( createTriangleMesh() );
// シーンの作成
// 3Dシーンの奥行きを表現するため、Zバッファを有効にする
Scene scene = new Scene( root , 1000 , 750 , true );
scene.setFill( Color.web( "9FCC7F" ) );
// カメラ設定
PerspectiveCamera camera = new PerspectiveCamera( true );
camera.setFarClip( 300 );
camera.setTranslateZ( -50 );
scene.setCamera( camera );
// 光源設定
LightBase light = new PointLight();
light.setTranslateZ( -50 );
root.getChildren().add( light );
// ウィンドウ表示
primaryStage.setScene( scene );
primaryStage.show();
}
/**
* トライアングル・メッシュを作成
*
* 【メッシュ】
* p0┏━┓p3
* ┃\┃
* p1┗━┛p2
*
* 【テクスチャ】
* t0┏━┓t3
* ┃ ┃
* t1┗━┛t2
*
* @return
*/
public Node createTriangleMesh()
{
// メッシュビューを作成
MeshView meshView = new MeshView();
// メッシュを作成
TriangleMesh mesh = new TriangleMesh();
float[] points = { -2 ,-2 ,0 , // p0
-2 ,2 ,0 , // p1
2 ,2 ,0 , // p2
2 ,-2 ,0 }; // p3
float[] texCoords = { 0 , 0 , // t0
0 , 1 , // t1
1 , 1 , // t2
1 , 0 }; // t3
int[] faces = { 0 , 0 , 1 , 1 , 2 , 2,
2 , 2 , 3 , 3 , 0 , 0 };
mesh.getPoints().addAll( points );
mesh.getTexCoords().addAll( texCoords );
mesh.getFaces().addAll( faces );
// マテリアルを作成
PhongMaterial material = new PhongMaterial();
// メッシュを登録
meshView.setMesh( mesh );
meshView.setMaterial( material );
meshView.setCullFace(CullFace.NONE);
// テキスチャアニメーション開始
new TextureAnimation( meshView ).start();
return meshView;
}
/**
* アニメーションタイマー・クラス
*/
private class TextureAnimation extends AnimationTimer
{
// アニメーション対象ノード
private MeshView meshView = null;
private Image[] images = null;
// アニメーション間隔(nano sec)
private long duration = 500 * 1000000L; // 500ミリ秒
private long startTime = 0;
private long beforeCount = -1;
public TextureAnimation( MeshView meshView )
{
// 内部変数の初期化
this.meshView = meshView;
// アニメーション画像の読込
images = new Image[2];
images[0] = new Image( new File( "img/chara_anime_01.gif" ).toURI().toString() );
images[1] = new Image( new File( "img/chara_anime_02.gif" ).toURI().toString() );
}
@Override
public void handle( long now )
{
// アニメーションの開始時間を取得
if( startTime == 0 ){ startTime = now; }
// アニメーションカウントを計算
// カウントが進んでいない場合は、処理を終了
Long count = ( now - startTime ) / duration;
if( beforeCount != count ){ beforeCount = count; }
else{ return; }
// 画像番号を計算
int index = 0;
if( count % 2 == 1 ){ index = 0; }
else{ index = 1; }
// マテリアルの再設定
PhongMaterial material = (PhongMaterial) meshView.getMaterial();
material.setDiffuseMap( images[ index ] );
meshView.setMaterial( material );
}
}
}
◇ リソース
(chara_anime_01.gif)
(chara_anime_02.gif)
◇ 実行結果
◇ 解説
- アニメーションはAnimationTimerクラスを継承したTextureAnimationクラスにより行う(104行目、112行目~159行目)。
- 一定間隔で呼ばれるhandle関数内でアニメーションカウントを計算し(138行目~144行目)、アニメーションカウントが偶数/奇数でテクスチャ画像を切り替えている(147行目~154行目)。
■ 参照
- JavaDoc - クラスTriangleMesh
- JavaDoc - インタフェースObservableFloatArray
改訂履歴・2015年10月29日 改訂。『メッシュ・アニメーション』を別記事として分離